#![no_main]
#![no_std]
#![feature(asm)]
use panic_halt as _;


extern "C" {
	static mut _stack_top: u32;
}


fn io_write(reg: u32, val: u32) {
    unsafe { *(reg as *mut u32)= val; }
}

fn io_read(reg: u32) -> u32 {
    unsafe { *(reg as *const u32) }
}

pub fn uart_init(){
    unsafe {
        const BASE:u32=0x3F000000;
        // turn off
        *((BASE+0x00201030) as *mut u32) |= 0 as u32;

        //clear int
        *((BASE+0x00201044) as *mut u32) = 0x7FF as u32;
        //115200
        *((BASE+0x00201024) as *mut u32) = 0x7FF as u32;

        //fbrd
        *((BASE+0x00201028) as *mut u32) = 0xB as u32;
        //8n1
        *((BASE+0x0020102C) as *mut u32) = 0b11 << 5 as u32;

        //enable tx rx
        *((BASE+0x00201030) as *mut u32) = 0x301 as u32;
    }
}


pub fn uart_send(byte: u8) {
    unsafe {
        const BASE:u32 = 0x3F000000;
        while (*((BASE+0x00201018) as *mut u32) & 0x20!=0) {
        }
        *((BASE +0x00201000) as *mut u32)= byte as u32;
    }
}

fn write_string(msg: &str) {
    for c in msg.chars() {
        uart_send(c as u8)
    }
}


#[no_mangle]
pub unsafe fn _start() {
    asm!("
    mrc p15, #0, r1, c0, c0, #5
    and r1, r1, #3
    cmp r1, #0
    bne halt 

    mrs r0, cpsr
    ldr sp, = _stack_top
    ldr fp, = _stack_top
    
    // set sp in abt mode.
    bic r1, r0, #0x1F
    orr r1, r1, #0x17
    msr cpsr_c,r1
    mov sp, #0x1000
    
    // set sp in undf mode.
    bic r1, r0, #0x1F
    orr r1, r1, #0x1B
    msr cpsr_c,r1
    mov sp, #0x1000
    
    // set sp in irq mode.
    bic r1, r0, #0x1F
    orr r1, r1, #0x12
    msr cpsr_c,r1
    mov sp, #0x2000
    //ldr sp,= stack_irq
    
    // set sp in svc mode.
    bic r1, r0, #0x1F
    orr r1, r1, #0x13
    msr cpsr_c, r0
    mov sp, #0x3000
    //ldr sp,= stack_svc
    bl main

    halt:
    wfe
    b halt
    "
);
    main();
}

#[no_mangle]
fn main() {
    uart_init();
    write_string("Hello,liteos cortex-a7!\n");

    loop{
    }
}
